package com.xiaolong.cloud.feign.adapter;


import com.alibaba.fastjson2.JSON;
import com.xiaolong.cloud.feign.exception.FeignDecoderException;
import com.xiaolong.cloud.feign.exception.ServiceInvocationProcessException;
import com.xiaolong.cloud.feign.exception.UpstreamServiceException;
import com.xiaolong.common.context.ModelViewResponse;
import feign.Response;
import feign.Util;
import feign.codec.Decoder;

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FeignClintDecoder implements Decoder {
    private static final Logger log = LoggerFactory.getLogger(FeignClintDecoder.class);

    @Override
    public Object decode(Response response, Type type) {
        try {
            String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
            ModelViewResponse<?> baseResponse = JSON.parseObject(bodyStr, ModelViewResponse.class);
            if (baseResponse.getCode() != 200) {
                throw new UpstreamServiceException(baseResponse.getCode(), baseResponse.getMessage());
            }
            if (Objects.isNull(baseResponse.getData())) {
                return null;
            }
            if (type instanceof Class) {
                return !Objects.equals(type, String.class) && !type.getClass().isPrimitive() ? JSON.parseObject(baseResponse.getData().toString(), type) : baseResponse.getData();
            } else if (type instanceof ParameterizedType) {
                return JSON.parseObject(baseResponse.getData().toString(), type);
            } else if (type instanceof TypeVariable) {
                return JSON.parseObject(baseResponse.getData().toString(), type);
            } else if (type instanceof GenericArrayType) {
                return JSON.parseObject(baseResponse.getData().toString(), type);
            } else if (type instanceof WildcardType) {
                return JSON.parseObject(baseResponse.getData().toString(), type);
            } else {
                throw new FeignDecoderException(bodyStr);
            }
        } catch (Throwable throwable) {
            throw new ServiceInvocationProcessException(throwable);
        }
    }
}
